import {
  HttpException,
  HttpStatus,
  Injectable,
  OnApplicationBootstrap,
} from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { Users } from './entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { WechatUserInfo } from '../auth/auth.interface';
import { QueryUserDto } from './dto/find-user.dto';
import { compareSync } from 'bcryptjs';

@Injectable()
export class UsersService implements OnApplicationBootstrap {
  constructor(
    @InjectRepository(Users)
    private userRepository: Repository<Users>,
  ) {}
  async onApplicationBootstrap() {
    const adminUser = await this.userRepository.findOne({
      where: {
        account: '1624362469',
      },
    });
    if (!adminUser) {
      const data = new CreateUserDto();
      Object.assign(data, {
        account: '1624362469',
        nickname: '陶奇林',
        password: '147258369TQLtql',
        role: 'root',
      });
      await this.create(data);
    }
  }
  async create(createUserDto: CreateUserDto) {
    // return 'This action adds a new user';
    const { account } = createUserDto;

    const existUser = await this.userRepository.findOne({
      where: { account },
    });
    if (existUser) {
      throw new HttpException('用户名已存在', HttpStatus.BAD_REQUEST);
    }

    const newUser = await this.userRepository.create(createUserDto);
    return await this.userRepository.save(newUser);
  }

  async registerByWechat(userInfo: WechatUserInfo) {
    const { nickname, openid, headimgurl } = userInfo;
    const newUser = await this.userRepository.create({
      nickname,
      openid,
      avatar: headimgurl,
    });
    return await this.userRepository.save(newUser);
  }

  async findByOpenid(openid: string) {
    return await this.userRepository.findOne({ where: { openid } });
  }

  async findAll(query?: QueryUserDto) {
    const { pageNum = 1, pageSize = 10, sortBy, role, ...params } = query;
    const qb = this.userRepository.createQueryBuilder('user');
    if (sortBy) {
      const sortByObject = JSON.parse(sortBy);
      Object.keys(sortBy).forEach((key) =>
        qb.orderBy(`user.${key}`, sortByObject[key]),
      );
    }
    if (role) qb.andWhere(`post.role = :role`, { role: role });
    if (params) {
      Object.keys(params).forEach((key) => {
        if (params[key])
          qb.andWhere(`post.${key} = :${key}`, { [key]: params[key] });
      });
    }
    const count = await qb.getCount();
    qb.take(pageSize);
    qb.skip(pageSize * (pageNum - 1));
    const users = await qb.getMany();
    return { list: users, count: count };
  }

  async findOne(id: string) {
    return await this.userRepository.findOneBy({ id: id });
  }

  async update(id: string, updateUserDto: UpdateUserDto) {
    const existUser = await this.userRepository.findOneBy({ id: id });
    if (!existUser) {
      throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
    }
    const userToUpdate = this.userRepository.merge(existUser, updateUserDto);
    return await this.userRepository.save(userToUpdate);
  }

  async remove(id: string) {
    const existUser = await this.userRepository.findOneBy({ id: id });
    if (!existUser) {
      throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
    }
    return await this.userRepository.remove(existUser);
  }

  /**
   * 密码重置
   * @param id
   * @returns
   */
  async resetPassword(id: string) {
    const existUser = await this.userRepository.findOneBy({ id: id });
    if (!existUser) {
      throw new HttpException(`id为${id}的用户不存在`, HttpStatus.FORBIDDEN);
    }
    const userToUpdate = this.userRepository.merge(existUser, {
      password: '123456',
    });
    return await this.userRepository.save(userToUpdate);
  }

  /**
   * 修改用户密码
   * @param updateUserId 修改对象
   * @param oldPassword 旧密码
   * @param newPassword 新密码
   */
  async updatePassword(
    updateUserId: string,
    oldPassword: string,
    newPassword: string,
  ) {
    const existUser = await this.userRepository
      .createQueryBuilder('users')
      .addSelect('users.password')
      .where('users.id=:id', { id: updateUserId })
      .getOne();
    if (!existUser) {
      throw new HttpException('用户不存在！', HttpStatus.FORBIDDEN);
    }

    if (!compareSync(oldPassword, existUser.password)) {
      throw new HttpException('旧密码密码错误！', HttpStatus.FORBIDDEN);
    }

    const userToUpdate = this.userRepository.merge(existUser, {
      password: newPassword,
    });
    return await this.userRepository.save(userToUpdate);
  }
}
